package com.yfm.RpcServer;

import com.yfm.Bean.RpcRequest;
import com.yfm.Bean.RpcResponse;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import net.sf.cglib.reflect.FastClass;

import java.lang.reflect.InvocationTargetException;
import java.util.Map;

public class RpcServerHandle extends SimpleChannelInboundHandler<RpcRequest> {


    private final Map<String, Object> handlerMap;

    public RpcServerHandle(Map<String, Object> handlerMap) {
        this.handlerMap = handlerMap;
    }



    //todo 处理逻辑待处理

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, RpcRequest rpcRequest) throws Exception {
        RpcResponse response = new RpcResponse();
        response.setRequestId(rpcRequest.getRequestId());
        try {
            Object result = handle(rpcRequest);
            response.setResult(result);
        } catch (Exception e) {
         //   LOGGER.error("handle result failure", e);
            response.setException(e);
        }

        System.out.println(response.toString());
        // 写入 RPC 响应对象并自动关闭连接
        ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE);


    }

    private Object handle(RpcRequest rpcRequest) throws InvocationTargetException {

        System.out.println(rpcRequest.getInterfaceName());
        String name = rpcRequest.getInterfaceName();
        String version = rpcRequest.getServiceVersion();
        if(version!=null && !version.isEmpty())
        {
            name = name+"-" + version;
        }
        Object serviceBean = handlerMap.get(name);
        if(serviceBean == null){
            throw  new RuntimeException(String.format("can not find service bean by key: %s", name));
        }
        Class<?> serviceClass = serviceBean.getClass();
        String MethodName = rpcRequest.getMethodName();
        Object[] parameters =  rpcRequest.getParameters();
        Class<?>[] parameterTypes = rpcRequest.getParameterTypes();
        FastClass fastClass = FastClass.create(serviceClass);
        return fastClass.getMethod(MethodName,parameterTypes).invoke(serviceBean,parameters);

    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {

        ctx.close();
    }
}
